/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <MBT_Engine.h>
#include <node后端.h>
#include <节点数据声明.h>
#include <节点编辑.h>
#include <Context/数据创建销毁.h>
#include <matXX.h>
#include <JIT.h>

#include <atomic>
#include <Json.h>

#include <UI/ui绘制模板.h>


#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"

#include "资源读写.h"



#define DEF_视口手柄元素网格_轴线_移动 0
#define DEF_视口手柄元素网格_箭头X_移动 1
#define DEF_视口手柄元素网格_箭头Y_移动 2
#define DEF_视口手柄元素网格_箭头Z_移动 3

#define DEF_视口手柄元素网格_万向_旋转 4
#define DEF_视口手柄元素网格_线圈X_旋转 5
#define DEF_视口手柄元素网格_线圈Y_旋转 6
#define DEF_视口手柄元素网格_线圈Z_旋转 7

#define DEF_视口手柄元素网格_x轴线 8
#define DEF_视口手柄元素网格_y轴线 9
#define DEF_视口手柄元素网格_z轴线 10

#define DEF_视口手柄元素总数量 11

#define DEF_输入插座标题 (u"输入插座")
#define DEF_输出插座标题 (u"输出插座")

#define DEF_手柄端点大小 20



enum E_物体数据类型 {
	e_模型,
	e_八叉树,
	e_射线拾取点,
	e_范围拾取点,
	e_射线拾取八叉树,
	e_范围拾取八叉树,
	//e_材质节点树,
	e_节点视口链接节点树,
	E_线,
};



typedef struct {
	C_节点基类*		node;
	E_节点更新方式	更新方式;
}S_编辑物体更新节点;


typedef struct {
	std::string		m_Path;
	E_节点更新方式	更新方式;
}S_库节点加载;


struct S_界面框架构建 {
	S_界面框架构建();
	virtual void f_保存界面框架(FILE* f) = 0;
	virtual void f_加载界面框架(FILE* f) = 0;
};

struct S_插件创建物体 {
	std::vector<S_物体*> m_物体;

	fn_plugin_物体创建销毁 mf_物体创建;
	fn_plugin_物体创建销毁 mf_物体销毁;
	
	//f_plugin_选择物体变换 mf_选择物体变换;
	fn_plugin_物体选择更新 mf_物体选择;
	fn_plugin_物体选择更新 mf_物体更新;

	bool m_拾取;
	bool m_渲染;
	bool m_可操作;
};

//class C_操作物体 : public S_物体 {
//public:
//	std::u16string m_网格节点;
//};



struct S_框架 {
	static S_Engine* engine;

	static uint32 版本号[2];
	

	static S_管线* g_索引绘制线管;
	static S_管线* g_线段绘制线管;
	static S_着色* g_单色Shader;
	
	
	
	static S_材质管线* g_体素BOX材质;
	static S_材质管线* g_线段绘制材质;
	static S_材质管线* g_VecSphere材质;
	static S_材质管线* g_Cube材质;
	static S_材质管线* g_索引绘制材质;
	//static S_材质* g_选择物体材质;
	//static S_纹理集* g_界面图像元素;


	
	static S_物体*				g_场景方向轴;
	static S_物体*              g_基准网格线;
	


	static std::vector<S_物体*> g_变换手柄方向线;
	static std::vector<S_物体*> g_变换手柄圆圈线;
	static std::vector<S_物体*> g_变换手柄轴向线;
	static std::vector<S_物体*> g_变换手柄移动箭头;
	static std::vector<S_物体*> g_变换手柄缩放端点;
	static S_MeshTranformProp	G变换手柄外接圆绘制属性;
	static S_MeshTranformProp	G变换手柄方向线绘制属性;
	static S_MeshTranformProp	G变换手柄端箭头绘制属性[3];
	static S_材质管线*			g_手柄线材质;
	static S_材质管线*			g_手柄面材质;
	
	static std::set<S_摄像机*>	g_视口相机;
	
	static S_物体*				g_当前独立显示物体;
	static S_物体*				g_Debug物体;

	//static std::map<uint64, std::vector<S_物体*>> g_场景辅助物体;
	static S_Tranform								g_变换手柄属性;
	static std::vector<S_物体*>						g_场景辅助物体;
	static std::map<uint64, std::vector<S_物体*>>	g_视口操作手柄;
	static std::set<S_物体*>						g_拾取物体;

	
	static E_物体数据类型	g_当前独显物体类型;

	static E_变换		g_变换手柄类型;

	static uint32		g_拾取手柄;
	static E_变换		g_物体变换方式;
	static E_轴向		g_操作变换轴;
	static bool			g_变换开关;

	static vec3			g_视线向量;
	static vec2			g_鼠标起始坐标;

	static int32		g_标记变换更新后事件;
	static uint32		g_文件备份数量;

	static bool			g_开启节点移动;

	static S_Scene*				g_小组件场景;
	static fp_无参数函数指针	gfu_更新选择节点;

	static vec2		g节点创建初始位置;



	
	static bool		g_播放帧;
	static int32	g_渲染预览模式;
	
	
	static S_Prop枚举项* g_视口物体渲染模式项_光追;
	static S_Prop枚举项* g_视口物体渲染模式项;
	static S_Prop枚举项* g_视口物体显示模式项;
	static S_Prop枚举项* g_曲线视口数据类型;
	
	static S_Prop枚举项* g_多选物体显示模式项_开启;
	static S_Prop枚举项* g_多选物体显示模式项_关闭;

	static S_Prop枚举项* g_物体遮罩类型项;

	static std::vector<S_标题和图标> g标题和图标_节点树类型;

	
	
	static E_物体类型	g当前编辑对象类型;

	static std::vector<S_MapPtrItem> g_材质节点树;


	static std::vector<S_Window*>	g_主窗口;
	static std::vector<S_Window*>	g_新窗口临时容器;
	


	static C_Widget*		g_ui文件对话框;
	static C_Widget*		g_ui_帮助弹出窗口;
	static C_Widget*		g_ui_加载保存信息框;

	static S_Window*		g_设置窗口;
	static S_Window*		g_文件窗口;
	
	

	static C_Widget*				g_ui顶层画布;
	static ui_绘制模板_预设图形*	m_全屏链接线背景绘制;
	static ui_绘制模板_行文本绘制*	m_全屏链接线字符绘制;
	static ui_绘制模板_图标*		m_全屏链接线图标绘制;
	static ui_绘制模板_自定义线*	m_全屏链接线绘制;

	static S_界面框架构建*			g_界面构建;


	static std::filesystem::path    m_库默认路径;
	static std::filesystem::path    m_扩展模块源码路径;
	//static JSONValueNode* m_配置;
	static std::vector<std::u16string>	g_最近打开文件;



	//===================== 物体 ============================
	static std::map<std::u16string, S_插件创建物体>			g_插件后端物体;
	static std::map<std::u16string, S_变换操作插件构建参数> g_插件_变换操作;

	static std::map<std::u16string, S_Object*>	g_物体节点;
	//static std::vector<S_Object*>				g_场景节点;
	static std::unique_ptr<S_Object>			g_场景节点;



	//=================== 曲线编辑 ==========================
	static std::map<const S_物体*, std::vector<uvec2>> g_选择端点;




	/************************** 界面 ************************/
	static C_渲染层分配	m_全局底层渲染层ID分配;
	static C_渲染层分配	m_工作区视口渲染层ID分配;
	static C_渲染层分配	m_工作区属性面板渲染层ID分配;
	static C_渲染层分配	m_工作区视口内部面板渲染层ID分配;



	static S_节点框架 g_节点框架;

	static C_资源异步加载保存 g_资源加载保存;


	S_框架();
	~S_框架();

	static void	init();
	static void	close();


	static void			f_初始化预设资源(S_设备环境& ctx);
	static S_Window*	f_创建窗口到列队(ivec2 size, bool 显示 = true, E_窗口类型 窗口类型 = E_窗口类型::E_Win32);
	static void			f_从列队销毁窗口(int32 loc = -1);
	static void			f_销毁列队窗口();
	static void			f_刷新窗口();

	
};





struct S_主题颜色 {
	static S_RGBA8UI uic_时间轴时间区;
	static S_RGBA8UI uic_时间网格线;
	
	static S_RGBA8UI uic_当前时间线;
	static S_RGBA8UI uic_节点插座文字;
	static S_RGBA8UI uic_节点剪刀线;
	static S_RGBA8UI uic_节点链接线;
	static S_RGBA8UI uic_节点插座;
	static S_RGBA8UI uic_节点面板焦点;
	static S_RGBA8UI uic_节点框;

	static S_RGBA8UI uic_视口手柄X;
	static S_RGBA8UI uic_视口手柄Y;
	static S_RGBA8UI uic_视口手柄Z;

	static S_RGBA8UI uic_选框面颜色;
	static S_RGBA8UI uic_选框边颜色;

	static S_RGBA8UI uic_物体焦点颜色;
	static S_RGBA8UI uic_物体选框颜色;
	static S_RGBA8UI uic_物体选框边颜色;

	static S_RGBA8UI uic_工作区页面背景;
	static S_RGBA8UI uic_工作区背景;
	static S_RGBA8UI uic_状态条背景;

	//static std::string uic_节点图标集;

	static S_RGBA8UI uic_焦点;
	static S_RGBA8UI uic_R;
	static S_RGBA8UI uic_G;
	static S_RGBA8UI uic_B;
	static S_RGBA8UI uic_C;

	static S_RGBA8UI uic_RG;
	static S_RGBA8UI uic_RB;
	static S_RGBA8UI uic_GB;



	S_主题颜色();
};

struct S_主题图标 {
	static std::string ico_变换移动;
	static std::string ico_变换旋转;
	static std::string ico_变换缩放;

	S_主题图标();
};


Inline uint64 f_字符串名称转换(const int8 str[]) {
	uint64 字符串构建整数 = 0;
	for (uint8 i = 0; str[i] != '\0'; 字符串构建整数 |= (str[i] << i), ++i) if (i >= 8) break;
	return 字符串构建整数;
}



enum E_工程文件块类型 : uint64 {
	e_工程文件块_文件头 = DEF_字符串拼接ID('p', 'r', 'o', 'p', 's', '\0', '\0', '\0'),

	e_工程文件块_属性变量 = DEF_字符串拼接ID('p', 'r', 'o', 'p', 's', '\0', '\0', '\0'),

	//e_工程文件块_数组F8 = DEF_字符串拼接ID('a', 'r', 'r', 'a', 'y', 'f', '8', '\0'),
	//e_工程文件块_数组F16 = DEF_字符串拼接ID('a', 'r', 'r', 'a', 'y', 'f', '1', '6'),
	//e_工程文件块_数组F32 = DEF_字符串拼接ID('a', 'r', 'r', 'a', 'y', 'f', '3', '2'),
	//e_工程文件块_数组F64 = DEF_字符串拼接ID('a', 'r', 'r', 'a', 'y', 'f', '6', '4'),

	//e_工程文件块_vec2 = DEF_字符串拼接ID('v', 'e', 'c', '2', '\0', '\0', '\0', '\0'),
	//e_工程文件块_vec3 = DEF_字符串拼接ID('v', 'e', 'c', '3', '\0', '\0', '\0', '\0'),
	//e_工程文件块_vec4 = DEF_字符串拼接ID('v', 'e', 'c', '4', '\0', '\0', '\0', '\0'),

	//e_工程文件块_数组vec2 = DEF_字符串拼接ID('v', 'e', 'c', '2', 's', 'z', '\0', '\0'),
	//e_工程文件块_数组vec3 = DEF_字符串拼接ID('v', 'e', 'c', '3', 's', 'z', '\0', '\0'),
	//e_工程文件块_数组vec4 = DEF_字符串拼接ID('v', 'e', 'c', '4', 's', 'z', '\0', '\0'),

	//e_工程文件块_节点树 = DEF_字符串拼接ID('N', 'o', 'd', 'e', 'T', 'r', 'e', 'e'),
	//e_工程文件块_节点 = DEF_字符串拼接ID('N', 'o', 'd', 'e', '\0', '\0', '\0', '\0'),

	e_工程文件块_全局状态   = DEF_字符串拼接ID('q', 'j', 'z', 't', '\0', '\0', '\0', '\0'),
};

enum E_编辑操作类型 : uint64 {
	e_操作类型_变换移动 = E_变换::e_移动,
	e_操作类型_变换旋转 = E_变换::e_旋转,
	e_操作类型_变换缩放 = E_变换::e_缩放,
	e_操作类型_添加物体,
	e_操作类型_删除物体,
	e_操作类型_拾取物体,
	e_操作类型_链接节点连接线,
	e_操作类型_切断节点连接线,
	e_操作类型_删除节点,
	e_操作类型_移动节点,
};



struct S_快捷键 {
	static uint8 g_移动快捷键[4];
	static uint8 g_旋转快捷键[4];
	static uint8 g_缩放快捷键[4];

	S_快捷键();
};


struct S_剪切板 {
	S_剪切板();
	~S_剪切板();
	virtual void f_复制() = 0;
	virtual void f_粘贴() = 0;

	static S_剪切板* f_get();
};




Inline void f_global_物体显示模式_打开焦点(S_物体* 物体, uint32 实例ID) {
	switch (物体->m_Type) {
	case E_物体类型::t_多边形:
		f_ob_set颜色2(物体, S_节点UI主题::uic_模型面, 实例ID, 1);
		f_ob_set颜色2(物体, S_节点UI主题::uic_模型线, 实例ID, 2);
		f_ob_set颜色2(物体, S_节点UI主题::uic_模型线, 实例ID, 3);
	case E_物体类型::t_网格物体:
	case E_物体类型::t_实例:
		
		f_ob_set颜色2(物体, S_节点UI主题::uic_模型焦点, 实例ID, 0);
		if (物体->m_DataNum) {
			//物体->f_打开可视通道(0);
			
		}
		else {
			//if(物体->m_父物体) f_global_物体显示模式_打开焦点(物体->m_父物体, 实例ID);
		}

		break;
	}
	
}
Inline void f_global_物体显示模式_关闭焦点(S_物体* 物体, uint32 实例ID) {
	switch (物体->m_Type) {
	case E_物体类型::t_网格物体:
	case E_物体类型::t_多边形:
	case E_物体类型::t_实例:
		
		f_ob_set颜色2(物体, {}, 实例ID);
		if (物体->m_DataNum) {
			//物体->f_关闭可视通道(0);
			
		}
		else {
			//if (物体->m_父物体) f_global_物体显示模式_关闭焦点(物体->m_父物体, 实例ID);
		}

		break;
	}
}

void f_global_所在独显模型材质(uint16 模式 = 0xff00);


C_节点基类* f_global_get激活节点后端();
void f_global_clear激活节点();



void f_global_set激活节点(std::vector<C_节点基类*>& nodes);
void f_global_set激活物体(std::vector<C_节点基类*>& nodes);
std::vector<C_节点基类*>&	f_global_get激活节点();
//std::vector<C_节点基类*>	f_global_get激活可视物体节点();
//vec3						f_global_get物体包围中心点(const std::set<S_物体*>& obs);
vec3						f_global_get激活物体包围中心点();
uint32						f_global_get选中物体数量();


void                      f_global_set钉住节点(class C_节点面板* panel);
class C_节点面板*         f_global_get钉住节点();

//void						f_global_get选择物体();
//std::vector<S_物体拾取信息>	f_global_get编辑拾取物体();
//void						f_global_clear拾取物体();

void                        f_global_变换手柄到物体中心();

void                        f_frame_bind当前操作物体节点();
std::vector<C_节点基类*>    f_frame_get操作物体节点();


//Inline class C_节点面板* f_global_get节点面板组件(C_节点基类* node) {
//	assert(node->m_UI部件);
//	return (C_节点面板*)(node->m_UI部件);
//}
void						f_global_set切换物体编辑模式(S_Props& prop);



void f_global_set全局物体显示();
void f_global_set独立物体显示(C_节点树* node);


void f_global_update编辑对象();


S_Object*	f_global_大纲数据();
void		f_global_清除大纲数据();

std::unordered_map<std::u16string, S_物体*>&	f_global_渲染物体();
C_StrKey分配器&									f_global_渲染物体键值();


